<!DOCTYPE html>
<html>
    <head>
        <title>Memory</title>
        <link rel="stylesheet" href="style.css" type="text/css" media="screen" />
        <script type="text/javascript" src="js/jquery-1.7.2.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            Array.prototype.shuffle = function() {
                var s = [];
                while (this.length) s.push(this.splice(Math.random() * this.length, 1)[0]);
                while (s.length) this.push(s.pop());
                return this;
            } 
        </script>

        <!-- Copyright Robin Weidelid :) -->
        <script type="text/javascript">
            window.onload = initializeGame;
            document.onkeypress = keyPressedEvent;
            
            //declarations
            var numberOfCardPairs = 8;
            var nrClick = 0;
            var playerScore = 0;
            var numberOfCardPairsLeft = 0;
            var colorBucket = new Array();
            var availableColors = new Array();
            var cards = new Array();
            var firstPick;
            var selectedCard;
            var resetButtonSelected = false;
            var selectedBorderColor = "YELLOW";
            var notSelectedBorderColor = "BLACK";
            var timerId = 0;
            var time = 0;
            var cardTimeout = false;

            //Object
            function Color(color){
                this.color = color;
                this.taken = false;
            }
            
            //Object
            function Card(id, type){
                this.id = id;
                this.type = type;
                this.removed = false;
            }

            //Helper
            function randomValue(n){
                return Math.floor(Math.random()*10000) % n;
            }

            //Helper 
            function findNextAvailableCard(nr, direction){
                if(direction == "UP"){
                    var mod = nr % 4;
                    var startValue = nr-(nr % 4)-1; //för att komma till den övre raden.
                    var closest = nr;
                    var firstValue = true;
                    for(var i = startValue; i >= 0; i--){
                        //&& (Math.floor(i/4) >= Math.floor(closest/4))
                        if(!cards[i].removed 
                            && (((Math.abs((i%4)-mod) < Math.abs((closest%4)-mod)) /**/ ) 
                            || ((Math.abs((i%4)-mod) == Math.abs((closest%4)-mod)) && i > closest) || firstValue)){
                                
                            firstValue = false;
                            closest = i;
                        }
                    }
                    if(closest != nr){
                        return closest;
                    }
                } 
                else if (direction == "DOWN"){
                    var mod = nr % 4;
                    var startValue = nr+4-(nr%4); //för att komma till den nedre raden.
                    var closest = nr;
                    var firstValue = true;
                    for(var i = startValue; i < cards.length; i++){
                        //&&  (Math.floor(i/4) <= Math.floor(closest/4))
                        if(!cards[i].removed 
                            && (((Math.abs((i%4)-mod) < Math.abs((closest%4)-mod)) /**/ )
                            || ((Math.abs((i%4)-mod) == Math.abs((closest%4)-mod)) && i < closest) || firstValue)){
                                
                            firstValue = false;
                            closest = i;
                        }
                    }
                    if(closest != nr){
                        return closest;
                    }
                }
                else if (direction == "RIGHT"){
                    for(var i = nr+1; i < cards.length; i++){
                        if( !cards[i].removed ){
                            return i;
                        }
                    }
                }
                else if (direction == "LEFT"){
                    for(var i = nr-1; i >= 0; i--){
                        if( !cards[i].removed ){
                            return i;
                        }
                    }
                }
                return -1;
            }

            function keyPressedEvent(evt){
                evt = evt || window.event;
        
                var nr = selectedCard.id;
                var next = -1;
                switch(evt.keyCode){
                    case 13:
                        if(resetButtonSelected){
                            initializeGame();
                        }else{
                            chooseCard(nr);
                        }
                        break;
            
                    case 37:
                        if(!resetButtonSelected){
                            next = findNextAvailableCard(nr, "LEFT");
                        }else{
                            next = findNextAvailableCard(cards.length, "LEFT");
                        }
                        if(next != -1){
                            if(resetButtonSelected){
                                selectResetButton(false);
                            }else{
                                removeSelectMarker(nr);
                            }
                            removeSelectMarker(nr);
                            selectCard(next);
                        }else{
                            removeSelectMarker(nr);
                            selectResetButton(true);
                        }
                        break;
  
                    case 38:
                        if(!resetButtonSelected){
                            next = findNextAvailableCard(nr, "UP");
                            if(next != -1){
                                removeSelectMarker(nr);
                                selectCard(next);
                            }
                        }
                        break;
   
                    case 39:
                        if(!resetButtonSelected){
                            next = findNextAvailableCard(nr, "RIGHT");
                        }else{
                            next = findNextAvailableCard(-1, "RIGHT");
                        }
                        if(next != -1){
                            if(resetButtonSelected){
                                selectResetButton(false);
                            }else{
                                removeSelectMarker(nr);
                            }
                            selectCard(next);
                        }else{
                            removeSelectMarker(nr);
                            selectResetButton(true);
                        }
                        break;
  
                    case 40:
                        if(!resetButtonSelected){
                            next = findNextAvailableCard(nr, "DOWN");
                            if(next != -1){
                                removeSelectMarker(nr);
                                selectCard(next);
                            }
                        }
                        break;
                }
            }
            
            function removeSelectMarker(nr){
                document.getElementById("card"+nr).style.borderColor = notSelectedBorderColor;
            }
            
            function selectCard(nr){
                document.getElementById("card"+nr).style.borderColor = selectedBorderColor;
                selectedCard = cards[nr];
            }
            
            function selectResetButton(choice){
                if(choice){
                    resetButtonSelected = true;
                    document.getElementById("resetButtonDiv").style.borderColor = selectedBorderColor;
                    document.getElementById("resetButtonDiv").style.borderWidth = "3px";
                }else{
                    resetButtonSelected = false;
                    document.getElementById("resetButtonDiv").style.borderColor = null;
                    document.getElementById("resetButtonDiv").style.borderWidth = null;
                }
            }
            
            //TODO kanske dela upp? tre uppgifter i en funktion..
            function populateColorBucket() {
                var xmlhttp = new XMLHttpRequest();
                xmlhttp.open("GET", "colours.conf", false);
                xmlhttp.setRequestHeader('Content-Type', 'text/xml');
                xmlhttp.send("");
                var text =  xmlhttp.responseText;
                var splitTextArray = [];
                var splitTextArray = text.split(/\s+/);
                for(var i = 0; i < splitTextArray.length; i++){
                    if(splitTextArray[i].charAt(0) == "#"){
                        colorBucket.push(splitTextArray[i]);
                    }
                }
            }

            function initColors(){
                for(var i = 0; i < numberOfCardPairs; i++){
                    for(var x = 0; x < 2; x++){
                        availableColors.push(new Color(colorBucket[i]));
                    }
                }
            }
            
            function initDeck(){
                availableColors.shuffle();
                for(var i = 0; i < numberOfCardPairs*2; i++){
                    cards.push(new Card(i, availableColors[i].color));
                }
            }
            
            function initializeGame(){
                if(colorBucket.length == 0){
                    populateColorBucket();
                }
                if(cards.length != 0){
                    removeCards();
                    availableColors = new Array();
                    cards = new Array();
                }
                numberOfCardPairsLeft = numberOfCardPairs;
                selectResetButton(false);
                document.forms["scoreForm"].elements["playerscore"].value = 0;
                document.forms["scoreForm"].elements["playertime"].value = 0;
                hideEndScore();
                cardTimeout = false;
                time = 0;
                playerScore = 0;
                initColors();
                initDeck();
                printCards();
                selectCard(5);
                startTimer();
            }

            function checkIfPair(card1, card2){
                if(cards[card1].type == cards[card2].type){
                    return true;
                }
                return false;
            }
            
            function chooseCard(nr){
                if(!cardTimeout && !cards[nr].removed){
                    nrClick++;
                    switch(nrClick){
                        case 1:
                            firstPick = cards[nr];
                            showCard(nr);
                            break;
                        case 2:
                            if(firstPick.id != nr){
                                showCard(nr);
                                if(!checkIfPair(firstPick.id, nr)){
                                    updateScore(-1);
                                    cardTimeout = true;
                                    setTimeout('resetCards('+firstPick.id+','+nr+')',2000);
                                }
                                else{
                                    --numberOfCardPairsLeft;
                                    updateScore(1);
                                    cardTimeout = true;
                                    hideCards(firstPick.id, nr);
                                    if(numberOfCardPairsLeft <= 0){
                                        stopTimer();
                                        showEndScore();
                                        setTimeout('initializeGame()', 5000);
                                    }
                                }
                                firstPick = null;
                                nrClick = 0;
                            }else{
                                nrClick = 1;
                            }
                            break;
                        default: 
                            nrClick = 0;
                            break;
                    }
                }
            }
            
            function showCard(nr){
                document.getElementById("card"+nr).style.backgroundImage = "none";
                document.getElementById("card"+nr).style.backgroundColor = cards[nr].type;
            }
            
            function showEndScore(){
                document.getElementById("gameResultsDiv").style.visibility = "visible";
                document.getElementById("gameResultsLabel").innerHTML = "Score: "+playerScore+"<br />Time: "+time+"s<br />The game will reset in<br /> 5seconds.";
            }
            
            function hideEndScore(){
                document.getElementById("gameResultsDiv").style.visibility = null;
            }
            
            function startTimer(){
                if(timerId != 0){
                    stopTimer();
                }
                timerId = setInterval('tickTimer()',1000);
            }
            
            function stopTimer(){
                clearInterval(timerId);
            }
            
            function tickTimer(){
                time = document.forms["scoreForm"].elements["playertime"].value;
                time++;
                document.forms["scoreForm"].elements["playertime"].value = time;
            }
            
            function updateScore(dif){
                playerScore += dif;
                document.forms["scoreForm"].elements["playerscore"].value = playerScore;
            }
            
            function hideCard(nr){
                document.getElementById("card"+nr).style.visibility = "hidden";
                cards[nr].removed = true;
            }    
            
            function hideCards(card1, card2){
                document.getElementById("card"+card1).style.borderStyle = "dotted";
                document.getElementById("card"+card2).style.borderStyle = "dotted";
                setTimeout('hideCard('+card1+')', 2000);
                setTimeout('hideCard('+card2+')', 2000);
                cardTimeout = false;
            }
        
            function resetCard(nr){
                document.getElementById("card"+nr).style.backgroundColor = null;
                document.getElementById("card"+nr).style.backgroundImage = 'url("card_bg.gif")';
            }
            
            function resetCards(card1, card2){
                document.getElementById("card"+card1).style.backgroundColor = null;
                document.getElementById("card"+card1).style.backgroundImage = 'url("card_bg.gif")';
                document.getElementById("card"+card2).style.backgroundColor = null;
                document.getElementById("card"+card2).style.backgroundImage = 'url("card_bg.gif")';
                cardTimeout = false;
            }
        
            function removeCards(){
                var gameboardDiv = document.getElementById("gamediv");
                for(var i = 0; i < numberOfCardPairs*2; i++){
                    var element = document.getElementById("card"+i);
                    gameboardDiv.removeChild(element);
                }
            }
            
            function printCards(){
                var gameboardDiv = document.getElementById("gamediv");
                for(var i = 0; i < numberOfCardPairs*2; i++){
                    var aElement = document.createElement('a');
                    aElement.href = "javascript:chooseCard("+i+")";
                    aElement.id = "card"+i;
                    aElement.className = "cardlink";
                    gameboardDiv.appendChild(aElement);
                }
            }
        </script>

        <table id="mainTable">
            <tr>
                <td id="gameTd">
                    <div id="gamediv">

                    </div>
                </td>

                <td id="infomationTd">
                    <div id="informationDiv">
                        <form name="scoreForm">

                            <div id="logoDiv"><img src="logo.png"/></div>

                            <div id="scoreDiv">
                                <table id="playerscoreTable">
                                    <tr>
                                        <td><label for="playerscore">score</Label></td>
                                        <td><input name="playerscore" type="text" disabled="true"/></td>
                                    </tr>
                                    <tr>
                                        <td><label for="playertime">time</Label></td>
                                        <td><input name="playertime" type="text" disabled="true"/></td>
                                    </tr>
                                </table>
                            </div>

                            <div id="gameResultsDiv">
                                <Label id="gameResultsLabel">Score: xx<br />Time: xxs<br />The game will reset in<br /> 5seconds.</Label>
                            </div>

                            <div id="resetButtonDiv">
                                <center>
                                    <input name="resetButton" value="new game" type="button" onclick="initializeGame()"/>
                                </center>
                            </div>

                        </form>
                    </div>
                </td>
            </tr>
        </table>
    </body>
</html>
